import type { AxiosInstance, AxiosRequestConfig, CreateAxiosDefaults } from 'axios'
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { get } from 'lodash-es'

import cookies from '@/plugins/cookies'
import projectSetting from '@/settings/projectSetting'

import { ErrorConfig } from './config'

class Axios {
  private instance: AxiosInstance
  constructor(config: CreateAxiosDefaults) {
    this.instance = axios.create(config)
    this.setupInterceptors()
  }

  async request<T, R = ResponseResult<T>>(config: AxiosRequestConfig) {
    try {
      const res = await this.instance.request<R>(config)
      return Promise.resolve(res as unknown as T)
    } catch (e) {
      console.log(e)
      return Promise.reject(e)
    }
  }

  // 拦截器
  private setupInterceptors() {
    this.interceptorRequest()
    this.interceptorResponse()
  }

  // 请求拦截
  private interceptorRequest() {
    this.instance.interceptors.request.use(
      (config) => {
        const token = cookies.get('token')
        if (token) {
          config.headers[projectSetting.TOKEN_NAME] = token
        }
        return config
      },
      (error) => {
        return Promise.reject(error)
      },
    )
  }

  // 响应拦截
  private interceptorResponse() {
    this.instance.interceptors.response.use(
      (response) => {
        const {
          data: responseData,
          // request: { responseType },
        } = response
        const { code, data, msg } = responseData
        const errorMsg = msg || projectSetting.UNDERTAKE_ERROR
        switch (code) {
          case 200:
            return data
          default:
            ElMessage.error(errorMsg)
            return Promise.reject(new Error(errorMsg))
        }
      },
      (error) => {
        const status = get(error, 'response.status') as keyof typeof ErrorConfig
        error.message = ErrorConfig[status] || projectSetting.UNDERTAKE_ERROR
        ElMessage.error(error.message)
        return Promise.reject(error)
      },
    )
  }
}

export default Axios
